package com.hcj.springcloud.CommandPattern;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * 命令模式-demo
 * <pre>
 * 是一种数据驱动的设计模式，属于行为模式类别。
 * 请求作为命令包装在对象下并传递给调用者对象。
 * Invoker对象查找可以处理此命令的相应对象，并将该命令传递给执行该命令的相应对象。
 * <br>---------------概览-----------------<br>
 * 我们创建了一个作为命令的接口Order。
 * 我们创建了一个充当请求的Stock类。
 * 我们有具体的命令类BuyStock和SellStock实现Order接口，它将进行实际的命令处理。
 * 创建一个类Broker（经纪人），它充当调用者对象。它可以接受和下订单。
 * Broker对象使用命令模式来识别哪个对象将根据命令的类型执行哪个命令。
 * </pre>
 *
 * @author huangchangjin
 * @date 2023/11/28 14:38
 */
@Slf4j
public class Demo {
    static class Stock {
        protected String name;
        protected Integer quantity;

        public Stock(String name, Integer quantity) {
            this.name = name;
            this.quantity = quantity;
        }

        public void buy() {
            log.info("购买- name = {} 数量 = {}", name, quantity);
        }

        public void sell() {
            log.info("卖出- name = {} 数量 = {}", name, quantity);
        }
    }

    interface Order {
        void execute();
    }

    static class BuyCmd implements Order {
        private Stock stock;

        public BuyCmd(Stock stock) {
            this.stock = stock;
        }

        @Override
        public void execute() {
            stock.buy();
        }
    }

    static class SellCmd implements Order {
        private Stock stock;

        public SellCmd(Stock stock) {
            this.stock = stock;
        }

        @Override
        public void execute() {
            stock.sell();
        }
    }

    static class Broker {
        List<Order> orders = new ArrayList<>();

        /**
         * 接收订单
         */
        public void takeOrder(Order order) {
            orders.add(order);
        }

        /**
         * 处理订单
         */
        public void placeOrders() {
            for (Order order : orders) {
                order.execute();
            }
            orders.clear();
        }
    }

    @Test
    void test_main() {
        Broker broker = new Broker();
        Stock stock1 = new Stock("商品A", 1);
        Stock stock2 = new Stock("商品B", 2);
        Stock stock3 = new Stock("商品C", 3);
        broker.takeOrder(new SellCmd(stock1));
        broker.takeOrder(new SellCmd(stock2));
        broker.takeOrder(new SellCmd(stock3));

        broker.takeOrder(new BuyCmd(stock3));

        broker.placeOrders();
    }
}
